home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2010 April / PCWorld0410.iso / hity wydania / Blender 2.49b / blender-2.49b-windows.exe / $_4_ / .blender / scripts / mesh_solidify.py < prev    next >
Text File  |  2009-08-31  |  10KB  |  345 lines

  1. #!BPY
  2. """
  3. Name: 'Solidify Selection'
  4. Blender: 243
  5. Group: 'Mesh'
  6. Tooltip: 'Makes the mesh solid by creating a second skin.'
  7. """
  8.  
  9. __author__ = "Campbell Barton"
  10. __url__ = ("www.blender.org", "blenderartists.org")
  11. __version__ = "1.1"
  12.  
  13. __bpydoc__ = """\
  14. This script makes a skin from the selected faces.
  15. Optionaly you can skin between the original and new faces to make a watertight solid object
  16. """
  17.  
  18. # -------------------------------------------------------------------------- 
  19. # Solidify Selection 1.0 by Campbell Barton (AKA Ideasman42) 
  20. # -------------------------------------------------------------------------- 
  21. # ***** BEGIN GPL LICENSE BLOCK ***** 
  22. # This program is free software; you can redistribute it and/or 
  23. # modify it under the terms of the GNU General Public License 
  24. # as published by the Free Software Foundation; either version 2 
  25. # of the License, or (at your option) any later version. 
  26. # This program is distributed in the hope that it will be useful, 
  27. # but WITHOUT ANY WARRANTY; without even the implied warranty of 
  28. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
  29. # GNU General Public License for more details. 
  30. # You should have received a copy of the GNU General Public License 
  31. # along with this program; if not, write to the Free Software Foundation, 
  32. # Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA. 
  33. # ***** END GPL LICENCE BLOCK ***** 
  34. # -------------------------------------------------------------------------- 
  35.  
  36. from Blender import *
  37. import bpy
  38. import BPyMesh
  39. # reload(BPyMesh)
  40. import BPyMessages
  41. # reload(BPyMessages)
  42.  
  43. from BPyMathutils import angleToLength
  44.  
  45. # python 2.3 has no reversed() iterator. this will only work on lists and tuples
  46. try:
  47.     reversed
  48. except:
  49.     def reversed(l): return l[::-1]
  50.  
  51. def copy_facedata_multilayer(me, from_faces, to_faces):
  52.     '''
  53.     Tkes 2 lists of faces and copies multilayer data from 1 to another
  54.     make sure they are aligned, cant copy from a quad to a tri, used for solidify selection.
  55.     '''
  56.     
  57.     def copy_default_face(data):
  58.         face_from, face_to = data
  59.         face_to.mat = face_from.mat
  60.         face_to.smooth = face_from.smooth
  61.         face_to.sel = True
  62.         face_from.sel = False
  63.     
  64.     def copy_tex_face(data):
  65.         face_from, face_to = data
  66.         face_to.uv = [c for c in reversed(face_from.uv)]
  67.         face_to.mode = face_from.mode
  68.         face_to.flag = face_from.flag
  69.         face_to.image = face_from.image
  70.     
  71.     def copy_col_face(data):
  72.         face_from, face_to = data
  73.         face_to.col = [c for c in reversed(face_from.col)]
  74.     
  75.     # make a list of face_from, face_to pairs
  76.     #face_pairs = zip(faces_sel, [me_faces[len_faces + i] for i in xrange(len(faces_sel))])
  77.     face_pairs = zip(from_faces, to_faces)
  78.     
  79.     # Copy properties from 1 set of faces to another.
  80.     map(copy_default_face, face_pairs)
  81.     
  82.     for uvlayer in me.getUVLayerNames():
  83.         me.activeUVLayer = uvlayer
  84.         map(copy_tex_face, face_pairs)
  85.     
  86.     for collayer in me.getColorLayerNames():
  87.         me.activeColorLayer = collayer
  88.         map(copy_col_face, face_pairs)
  89.     
  90.     # Now add quads between if we wants
  91.  
  92.  
  93. Ang= Mathutils.AngleBetweenVecs
  94. SMALL_NUM=0.00001
  95.  
  96. def solidify(me, PREF_THICK, PREF_SKIN_SIDES=True, PREF_REM_ORIG=False, PREF_COLLAPSE_SIDES=False):
  97.     
  98.     # Main code function
  99.     me_faces = me.faces
  100.     faces_sel= [f for f in me_faces if f.sel]
  101.     
  102.     BPyMesh.meshCalcNormals(me)
  103.     normals= [v.no for v in me.verts]
  104.     vertFaces= [[] for i in xrange(len(me.verts))]
  105.     for f in me_faces:
  106.         no=f.no
  107.         for v in f:
  108.             vertFaces[v.index].append(no)
  109.     
  110.     # Scale the normals by the face angles from the vertex Normals.
  111.     for i in xrange(len(me.verts)):
  112.         length=0.0
  113.         if vertFaces[i]:
  114.             for fno in vertFaces[i]:
  115.                 try:
  116.                     a= Ang(fno, normals[i])
  117.                 except:
  118.                     a= 0    
  119.                 if a>=90:
  120.                     length+=1
  121.                 elif a < SMALL_NUM:
  122.                     length+= 1
  123.                 else:
  124.                     length+= angleToLength(a)
  125.             
  126.             length= length/len(vertFaces[i])
  127.             #print 'LENGTH %.6f' % length
  128.             # normals[i]= (normals[i] * length) * PREF_THICK
  129.             normals[i] *= length * PREF_THICK
  130.             
  131.             
  132.     
  133.     len_verts = len( me.verts )
  134.     len_faces = len( me_faces )
  135.     
  136.     vert_mapping= [-1] * len(me.verts)
  137.     verts= []
  138.     for f in faces_sel:
  139.         for v in f:
  140.             i= v.index
  141.             if vert_mapping[i]==-1:
  142.                 vert_mapping[i]= len_verts + len(verts)
  143.                 verts.append(v.co + normals[i])
  144.     
  145.     #verts= [v.co + normals[v.index] for v in me.verts]
  146.     
  147.     me.verts.extend( verts )
  148.     #faces= [tuple([ me.verts[v.index+len_verts] for v in reversed(f.v)]) for f in me_faces ]
  149.     faces= [ tuple([vert_mapping[v.index] for v in reversed(f.v)]) for f in faces_sel ]
  150.     me_faces.extend( faces )
  151.     
  152.  
  153.     
  154.     
  155.     # Old method before multi UVs
  156.     """
  157.     has_uv = me.faceUV
  158.     has_vcol = me.vertexColors
  159.     for i, orig_f in enumerate(faces_sel):
  160.         new_f= me_faces[len_faces + i]
  161.         new_f.mat = orig_f.mat
  162.         new_f.smooth = orig_f.smooth
  163.         orig_f.sel=False
  164.         new_f.sel= True
  165.         new_f = me_faces[i+len_faces]
  166.         if has_uv:
  167.             new_f.uv = [c for c in reversed(orig_f.uv)]
  168.             new_f.mode = orig_f.mode
  169.             new_f.flag = orig_f.flag
  170.             if orig_f.image:
  171.                 new_f.image = orig_f.image
  172.         if has_vcol:
  173.             new_f.col = [c for c in reversed(orig_f.col)]
  174.     """
  175.     copy_facedata_multilayer(me, faces_sel, [me_faces[len_faces + i] for i in xrange(len(faces_sel))])
  176.     
  177.     if PREF_SKIN_SIDES or PREF_COLLAPSE_SIDES:
  178.         skin_side_faces= []
  179.         skin_side_faces_orig= []
  180.         # Get edges of faces that only have 1 user - so we can make walls
  181.         edges = {}
  182.         
  183.         # So we can reference indicies that wrap back to the start.
  184.         ROT_TRI_INDEX = 0,1,2,0
  185.         ROT_QUAD_INDEX = 0,1,2,3,0
  186.         
  187.         for f in faces_sel:
  188.             f_v= f.v
  189.             for i, edgekey in enumerate(f.edge_keys):
  190.                 if edges.has_key(edgekey):
  191.                     edges[edgekey]= None
  192.                 else:
  193.                     if len(f_v) == 3:
  194.                         edges[edgekey] = f, f_v, i, ROT_TRI_INDEX[i+1]
  195.                     else:
  196.                         edges[edgekey] = f, f_v, i, ROT_QUAD_INDEX[i+1]
  197.         del ROT_QUAD_INDEX, ROT_TRI_INDEX
  198.         
  199.         # So we can remove doubles with edges only.
  200.         if PREF_COLLAPSE_SIDES:
  201.             me.sel = False
  202.         
  203.         # Edges are done. extrude the single user edges.
  204.         for edge_face_data in edges.itervalues():
  205.             if edge_face_data: # != None
  206.                 f, f_v, i1, i2 = edge_face_data
  207.                 v1i,v2i= f_v[i1].index, f_v[i2].index
  208.                 
  209.                 if PREF_COLLAPSE_SIDES:
  210.                     # Collapse
  211.                     cv1 = me.verts[v1i]
  212.                     cv2 = me.verts[vert_mapping[v1i]]
  213.                     
  214.                     cv3 = me.verts[v2i]
  215.                     cv4 = me.verts[vert_mapping[v2i]]
  216.                     
  217.                     cv1.co = cv2.co = (cv1.co+cv2.co)/2
  218.                     cv3.co = cv4.co = (cv3.co+cv4.co)/2
  219.                     
  220.                     cv1.sel=cv2.sel=cv3.sel=cv4.sel=True
  221.                     
  222.                     
  223.                     
  224.                 else:
  225.                     # Now make a new Face
  226.                     # skin_side_faces.append( (v1i, v2i, vert_mapping[v2i], vert_mapping[v1i]) )
  227.                     skin_side_faces.append( (v2i, v1i, vert_mapping[v1i], vert_mapping[v2i]) )
  228.                     skin_side_faces_orig.append((f, len(me_faces) + len(skin_side_faces_orig), i1, i2))
  229.         
  230.         if PREF_COLLAPSE_SIDES:
  231.             me.remDoubles(0.0001)
  232.         else:
  233.             me_faces.extend(skin_side_faces)
  234.             # Now assign properties.
  235.             """
  236.             # Before MultiUVs
  237.             for i, origfData in enumerate(skin_side_faces_orig):
  238.                 orig_f, new_f_idx, i1, i2 = origfData
  239.                 new_f= me_faces[new_f_idx]
  240.                 
  241.                 new_f.mat= orig_f.mat
  242.                 new_f.smooth= orig_f.smooth
  243.                 if has_uv:
  244.                     new_f.mode= orig_f.mode
  245.                     new_f.flag= orig_f.flag
  246.                     if orig_f.image:
  247.                         new_f.image= orig_f.image
  248.                     
  249.                     uv1= orig_f.uv[i1]
  250.                     uv2= orig_f.uv[i2]
  251.                     new_f.uv= (uv1, uv2, uv2, uv1)
  252.                 
  253.                 if has_vcol:
  254.                     col1= orig_f.col[i1]
  255.                     col2= orig_f.col[i2]
  256.                     new_f.col= (col1, col2, col2, col1)
  257.             """
  258.             
  259.             for i, origfData in enumerate(skin_side_faces_orig):
  260.                 orig_f, new_f_idx, i2, i1 = origfData
  261.                 new_f= me_faces[new_f_idx]
  262.                 
  263.                 new_f.mat= orig_f.mat
  264.                 new_f.smooth= orig_f.smooth
  265.             
  266.             for uvlayer in me.getUVLayerNames():
  267.                 me.activeUVLayer = uvlayer
  268.                 for i, origfData in enumerate(skin_side_faces_orig):
  269.                     orig_f, new_f_idx, i2, i1 = origfData
  270.                     new_f= me_faces[new_f_idx]
  271.                     
  272.                     new_f.mode= orig_f.mode
  273.                     new_f.flag= orig_f.flag
  274.                     new_f.image= orig_f.image
  275.                     
  276.                     uv1= orig_f.uv[i1]
  277.                     uv2= orig_f.uv[i2]
  278.                     new_f.uv= (uv1, uv2, uv2, uv1)
  279.             
  280.             for collayer in me.getColorLayerNames():
  281.                 me.activeColorLayer = collayer
  282.                 for i, origfData in enumerate(skin_side_faces_orig):
  283.                     orig_f, new_f_idx, i2, i1 = origfData
  284.                     new_f= me_faces[new_f_idx]
  285.                     
  286.                     col1= orig_f.col[i1]
  287.                     col2= orig_f.col[i2]
  288.                     new_f.col= (col1, col2, col2, col1)
  289.         
  290.     
  291.     if PREF_REM_ORIG:
  292.         me_faces.delete(0, faces_sel)
  293.  
  294.  
  295.  
  296.  
  297. def main():
  298.     scn = bpy.data.scenes.active
  299.     ob = scn.objects.active
  300.     
  301.     if not ob or ob.type != 'Mesh':
  302.         BPyMessages.Error_NoMeshActive()
  303.         return
  304.     
  305.     me = ob.getData(mesh=1)
  306.     if me.multires:
  307.         BPyMessages.Error_NoMeshMultiresEdit()
  308.         return
  309.     
  310.     # Create the variables.
  311.     PREF_THICK = Draw.Create(-0.1)
  312.     PREF_SKIN_SIDES= Draw.Create(1)
  313.     PREF_COLLAPSE_SIDES= Draw.Create(0)
  314.     PREF_REM_ORIG= Draw.Create(0)
  315.     
  316.     pup_block = [\
  317.     ('Thick:', PREF_THICK, -10, 10, 'Skin thickness in mesh space.'),\
  318.     ('Skin Sides', PREF_SKIN_SIDES, 'Skin between the original and new faces.'),\
  319.     ('Collapse Sides', PREF_COLLAPSE_SIDES, 'Skin between the original and new faces.'),\
  320.     ('Remove Original', PREF_REM_ORIG, 'Remove the selected faces after skinning.'),\
  321.     ]
  322.     
  323.     if not Draw.PupBlock('Solid Skin Selection', pup_block):
  324.         return
  325.     
  326.     is_editmode = Window.EditMode() 
  327.     if is_editmode: Window.EditMode(0)
  328.     
  329.     Window.WaitCursor(1)
  330.     
  331.     me = ob.getData(mesh=1)
  332.     solidify(me, PREF_THICK.val, PREF_SKIN_SIDES.val, PREF_REM_ORIG.val, PREF_COLLAPSE_SIDES.val)
  333.     
  334.     
  335.     Window.WaitCursor(0)
  336.     if is_editmode:    Window.EditMode(1)
  337.     
  338.     Window.RedrawAll()
  339.  
  340. if __name__ == '__main__':
  341.     main()